from datetime import datetime, timedelta
from typing import Annotated
from fastapi import APIRouter, Depends, Request

from sanren.utils import get_current_active_user
from application.http import models
from application.http.models import OemModel, CodeModel
from application.http.schemas import ApiSchemas
from application.http import schemas
from application.http.schemas.api.system.dashboard import CountField


router = APIRouter(prefix='/system/dashboard', tags=['System'])
module_name = '系统模块'


@router.post('/todolist', response_model=schemas.BaseApiOut)
async def todolist(
    current_user: Annotated[object, Depends(get_current_active_user)],
    request: Request,
):
    """
        待办事项
    """

    objs = OemModel.TenantDomain.where('deploy_status', 0).or_where('deploy_ssl_status', 0).all()

    return_data = []
    for item in objs:
        tmp_item = {}

        # 商户信息
        tmp_item['code'] = item.code

        # 任务 ： 当前只读取部署域名
        task = ''
        if item.deploy_status == 0:
            task += '自定义域名对接,'
        if item.deploy_ssl_status == 0:
            task += 'SSL 域名证书部署'
        tmp_item['task'] = task

        return_data.append(tmp_item)

    return {'data': return_data}


@router.post('/code_data', response_model=schemas.BaseApiOut)
async def code_data(
    current_user: Annotated[object, Depends(get_current_active_user)],
    request: Request,
    type: int = 1,
):
    """
        码数据
    """

    # 数据名
    category, date_list = get_date_name(type=type)

    return_data = {
        'category': category,
        'date_list': date_list,
        'code_line': get_code_data(type=type),
        'scan_log_line': get_scan_log_data(type=type),
    }

    return {'data': return_data}


@router.post('/count', response_model=schemas.BaseApiOut)
async def count(
    current_user: Annotated[object, Depends(get_current_active_user)],
    request: Request,
    post: ApiSchemas.system.CountField,
):
    """
        数据统计
    """

    total = {}

    if 'company_total' in post.field:
        # 注册企业
        total['company_total'] = int(get_company_total())

    if 'good_total' in post.field:
        # 录入商品量
        total['good_total'] = int(get_good_total())

    if 'abolish_total' in post.field:
        # 作废码量
        total['abolish_total'] = int(get_abolish_total())

    if 'code_total' in post.field:
        # 生码量
        total['code_total'] = int(get_code_total())

    if 'unabled_code_total' in post.field:
        # 未启用码量
        total['unabled_code_total'] = int(get_unabled_code_total())

    if 'only_create_code_total' in post.field:
        # 只生码码量
        total['only_create_code_total'] = int(get_only_create_code_total())

    if 'enabled_code_total' in post.field:
        # 启用码量
        total['enabled_code_total'] = int(get_enabled_code_total())

    if 'use_code_total' in post.field:
        # 可用码量
        use_code_total = int(get_code_total or 0) - int(get_unabled_code_total() or 0) - int(get_abolish_total() or 0)
        total['use_code_total'] = int(use_code_total)

    # 扫描量
    if 'scan_total' in post.field:
        total['scan_total'] = int(get_scan_total())

    # 扫描码量
    if 'scan_code_total' in post.field:
        total['scan_code_total'] = int(get_scan_code_total())

    return {'data': total}


def get_scan_total():
    return OemModel.CodeLog.count('id').first().id or 0


def get_scan_code_total():
    # 刮刮码
    scrape_code_total = OemModel.CodeLog.where('code_type', 1).select_raw('count(distinct(security_code)) as total').first().total or 0
    # 防伪码
    security_code_total = OemModel.CodeLog.where('code_type', 2).select_raw('count(distinct(security_code)) as total').first().total or 0
    # 流水号
    serial_code_total = OemModel.CodeLog.where('code_type', 3).select_raw('count(distinct(security_code)) as total').first().total or 0

    return int(scrape_code_total) + int(security_code_total) + int(serial_code_total)


def get_company_total():
    return OemModel.Company.count('id').first().id or 0


def get_good_total():
    return OemModel.Good.count('id').first().id or 0


def get_abolish_total():
    return CodeModel.Abolish.where('status', 2).sum('counts').first().counts or 0


def get_code_total():
    return CodeModel.Order.where('status', 2).select_raw('SUM(big_total + middle_total + small_total) as total').first().total or 0


def get_unabled_code_total():
    return CodeModel.Order.where('status', 2).where('code_enable', 0).select_raw('SUM(big_total + middle_total + small_total) as total').first().total or 0


def get_only_create_code_total():
    return CodeModel.Order.where('status', 2).where('query_type', 3).select_raw('SUM(counts) as total').first().total or 0


def get_enabled_code_total():
    return CodeModel.Order.where('status', 2).where('code_enable', 1).select_raw('SUM(big_total + middle_total + small_total) as total').first().total or 0


def get_date_name(type: int = 1):
    date_name_list = list()
    date_list = list()
    if type == 2:  # 月 默认 31天
        for i in range(31):
            date_info = datetime.now() - timedelta(days=(30 - i))
            week_index = date_info.weekday()
            date_name_list.append(date_info.strftime('%Y-%m-%d'))
            date_list.append(date_info.strftime('%Y-%m-%d'))
    else:  # 周
        weekname = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
        for i in range(7):
            date_info = datetime.now() - timedelta(days=(6 - i))
            week_index = date_info.weekday()
            date_name_list.append(weekname[week_index])
            date_list.append(date_info.strftime('%Y-%m-%d'))

    return date_name_list, date_list


def get_scan_log_data(type=1):
    # 时间段限制
    start_day = (datetime.now() - timedelta(days=31)).strftime('%Y-%m-%d') if type == 2 else \
                (datetime.now() - timedelta(days=7)).strftime('%Y-%m-%d')
    end_day = datetime.now().strftime('%Y-%m-%d')

    # 按照YYYYMMDD进行统计，可以有很多种
    res = OemModel.CodeLog.where(
        'created_at', '>=', start_day
    ).where(
        'created_at', '<=', end_day
    ).select_raw(
        "DATE_FORMAT(created_at, '%%Y-%%m-%%d') as date, count(*) as total"
    ).group_by_raw('date').all()

    res_data = dict()
    for item in res:
        res_data[item.date] = item.total

    line_data = list()
    count = 31 if type == 2 else 7
    for i in range(count):
        date_val = (datetime.now() - timedelta(days=count - i)).strftime('%Y-%m-%d')
        if date_val in res_data:
            line_data.append(res_data[date_val])
        else:
            line_data.append(0)

    return line_data


def get_code_data(type=1):
    # 时间段限制
    start_day = (datetime.now() - timedelta(days=31)).strftime('%Y-%m-%d') if type == 2 else \
                (datetime.now() - timedelta(days=7)).strftime('%Y-%m-%d')
    end_day = datetime.now().strftime('%Y-%m-%d')

    # 按照YYYYMMDD进行统计，可以有很多种
    res = OemModel.CodeLog.where(
        'created_at', '>=', start_day
    ).where(
        'created_at', '<=', end_day
    ).select_raw(
        "DATE_FORMAT(created_at, '%%Y-%%m-%%d') as date, count(distinct(security_code)) as total"
    ).group_by_raw('date').all()

    res_data = dict()
    for item in res:
        res_data[item.date] = item.total

    line_data = list()
    count = 31 if type == 2 else 7
    for i in range(count):
        date_val = (datetime.now() - timedelta(days=count - i)).strftime('%Y-%m-%d')
        if date_val in res_data:
            line_data.append(res_data[date_val])
        else:
            line_data.append(0)

    return line_data
